// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//                          avtDataObjectString.C                            //
// ************************************************************************* //

#include <avtDataObjectString.h>

// For NULL
#include <stddef.h>

#include <BadIndexException.h>
#include <ImproperUseException.h>


using std::vector;


// ****************************************************************************
//  Method: avtDataObjectString constructor
//
//  Programmer: Hank Childs
//  Creation:   May 25, 2001
//
//  Modifications:
//
//    Hank Childs, Sun Sep 16 16:06:57 PDT 2001
//    Removed initialization of old data members.
//
// ****************************************************************************

avtDataObjectString::avtDataObjectString()
{
    wholeString = NULL;
}


// ****************************************************************************
//  Method: avtDataObjectString destructor
//
//  Programmer: Hank Childs
//  Creation:   May 25, 2001
//
//  Modifications:
//
//    Hank Childs, Sun Sep 16 16:06:57 PDT 2001
//    Added destruction of character strings that were donated to this object.
//
// ****************************************************************************

avtDataObjectString::~avtDataObjectString()
{
    for (size_t i = 0 ; i < strs.size() ; i++)
    {
        if (ownString[i])
        {
            delete [] strs[i];
        }
    }
    if (wholeString != NULL)
    {
        delete [] wholeString;
        wholeString = NULL;
    }
}


// ****************************************************************************
//  Method: avtDataObjectString
//
//  Purpose:
//      Performs an append.  Since we are just keeping a reference to the
//      string, this is very cheap.
//
//  Arguments:
//      s       The string to append.
//      sN      The length of s.
//      os      Action item type.
//
//  Programmer: Hank Childs
//  Creation:   May 25, 2001
//
//  Modifications:
//
//    Hank Childs, Sun Sep 16 16:06:57 PDT 2001
//    Re-wrote function to reflect new data members.
//
// ****************************************************************************

void
avtDataObjectString::Append(char *s, int sN, APPEND_ACTION_ITEM os)
{
    char *str_to_copy = s;
    bool  do_we_own_string = false;
    switch (os)
    {
      case DATA_OBJECT_STRING_DOES_NOT_OWN_REFERENCE:
        do_we_own_string = false;
        break;

      case DATA_OBJECT_STRING_OWNS_REFERENCE_AFTER_CALL:
        do_we_own_string = true;
        break;

      case DATA_OBJECT_STRING_SHOULD_MAKE_COPY:
        {
            str_to_copy = new char[sN];
            for (int i = 0 ; i < sN ; i++)
            {
                str_to_copy[i] = s[i];
            }
            do_we_own_string = true;
        }
        break;

      default:
        EXCEPTION0(ImproperUseException);
    }
 
    strs.push_back(str_to_copy);
    lens.push_back(sN);
    ownString.push_back(do_we_own_string);

    if (wholeString != NULL)
    {
        delete [] wholeString;
        wholeString = NULL;
    }
}


// ****************************************************************************
//  Method: avtDataObjectString::GetString
//
//  Purpose:
//      Gets one of N strings that make up the total data object string.
//
//  Arguments:
//      n         Which string to get.
//      s         Where the string will be stored.
//      l         Where the length of the string will be stored.
//
//  Programmer:   Hank Childs
//  Creation:     May 26, 2001
//
//  Modifications:
//
//    Hank Childs, Sun Sep 16 16:06:57 PDT 2001
//    Added argument to reflect that this routine only gets a fraction of the
//    total argument.
//
// ****************************************************************************

void
avtDataObjectString::GetString(int n, char *&s, int &l)
{
    if (n < 0 || n >= (int)strs.size())
    {
        EXCEPTION2(BadIndexException, n, (int)strs.size());
    }

    s = strs[n];
    l = lens[n];
}


// ****************************************************************************
//  Method: avtDataObjectString::GetWholeString
//
//  Purpose:
//      Gets the whole data object string.  Note that this is typically not a
//      good thing to do since it doubles the required memory footprint.  This
//      is really only meant to be used by the non-UI processes, who don't want
//      to make multiple MPI calls.
//
//  Arguments:
//      s         Where the string will be stored.
//      l         Where the length of the string will be stored.
//
//  Programmer:   Hank Childs
//  Creation:     September 16, 2001
//
//  Modifications:
//    Brad Whitlock, Mon Sep 15 17:21:30 PDT 2014
//    Call a helper function to actually get the whole string if we need to
//    make it.
//
// ****************************************************************************

void
avtDataObjectString::GetWholeString(char *&s, int &l)
{
    if (wholeString)
    {
        s = wholeString;
        l = GetTotalLength();
    }
    else
    {
        wholeString = GetWholeString(l);
        s = wholeString;
    }
}

char *
avtDataObjectString::GetWholeString(int &l) const
{
    int totalLength = GetTotalLength();
    char *s = new char[totalLength];

    int nstrs  = strs.size();
    int offset = 0;
    for (int i = 0 ; i < nstrs ; i++)
    {
        for (int j = 0 ; j < lens[i] ; j++)
        {
            s[offset] = strs[i][j];
            offset++;
        }
    }

    l = totalLength;
    return s;
}

// ****************************************************************************
//  Method: avtDataObjectString::GetNStrings
//
//  Purpose:
//      Gets the total number of strings that comprise the total data object
//      string.
//
//  Returns:    The total number of strings that comprise the total data object
//              string.
//
//  Programmer: Hank Childs
//  Creation:   September 16, 2001
//
// ****************************************************************************

int
avtDataObjectString::GetNStrings(void) const
{
    return strs.size();
}


// ****************************************************************************
//  Method: avtDataObjectString::GetTotalLength
//
//  Purpose:
//      Gets the length of all of the strings in the data object string.
//
//  Returns:    The length of all of the string in bytes.
//
//  Programmer: Hank Childs
//  Creation:   September 16, 2001
//
// ****************************************************************************

int
avtDataObjectString::GetTotalLength(void) const
{
    int rv = 0;
    int nStrings = strs.size();
    for (int i = 0 ; i < nStrings ; i++)
    {
        rv += lens[i];
    }

    return rv;
}


